<template>
	<view class="map-container">
		<map
			class="map"
			:longitude="location.longitude"
		  :latitude="location.latitude"
			:markers="covers"
			:circles="circles"
		>
		</map>
		<!--默认插槽（定义打卡显示）-->
		<view v-if="$slots.default">
			<slot></slot>
		</view>
		<view
			v-else
			:class="isInArea ? 'in-area' : 'not-in-area'"
			@click="clockIn"
		>
			<view class="tip">
				<view class="inline">
					<view class="icon"></view>
					<view class="des">{{ isInArea ? yesLabel : noLabel }}</view>
				</view>
			</view>
			<view class="click-in-btn">
				<view class="txt">{{ btnLabel }}</view>
				<view class="time">{{ curTime }}</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		props: {
			// 打卡区域设置
			clockInArea: Array,
			// 刷新打卡区域频率
			refreshTimeout: {
				type: Number,
				default: 3000
			},
			btnLabel: {
				type: String,
				default: '打卡'
			},
			yesLabel: {
				type: String,
				default: '在打卡范围内'
			},
			noLabel: {
				type: String,
				default: '不在打卡范围内'
			},
			// 是否实时上报数据
			isReport: {
				type: Boolean,
				default: false
			}
		},
		data() {
			return {
				prevLocation: null,
				location: {
					latitude: 0,
					longitude: 0,
					radius: 150
				},
				circles: [],
				covers: [],
				isInArea: false,
				timer: null,
				curTime: null,
				timer2: null,
				distance: null,
			}
		},
		created() {
			this.loadClockInConfig()
			this.setTime()
		},
		destroyed() {
			this.timer && clearTimeout(this.timer)
			this.timer2 && clearTimeout(this.timer2)
		},
		methods: {
			loadClockInConfig() {
				this.setPunchzone(this.clockInArea)
				this.loadMyLocation(this.clockInArea)
			},
			loadMyLocation(areaLists) {
				this.timer = setInterval(async () => {
					// 获取位置
					const location = await this.getLocation()
					if (location) {
						let isRule = false // 是否有符合打卡规则
						let nearestVal = Infinity // 距离离近多少米
						let nearestIndex = 0 // 距离最近的打卡规则
						for (let i = 0; i < areaLists.length; i++) {
							const item = areaLists[i]
							const lat1 = item.latitude
							const lng1 = item.longitude
							const distance = item.distance
							const lat2 = location.latitude
							const lng2 = location.longitude
							const s = this.distanceOfTwoPoint(lat1, lng1, lat2, lng2)

							// 记录打卡规则中距离最小的位置
							if (s < nearestVal) {
								nearestVal = s
								nearestIndex = i
							}
							
							if (s <= distance) {
								isRule = true
								this.isInArea = true
								location.address = item.location // 记录符合打卡规则的地址
								location.ruleId = item.ruleId // 记录符合打卡规则
								this.location = item // 设置地图位置
								this.setLocation(location)
								this.distance = s // 记录打卡距离m
								break
							} else {
								this.isInArea = false
							}
						}
						
						// 如果所有规则都不符合打卡，地图定位在最近的打卡区域
						if (!isRule) {
							const result = areaLists[nearestIndex]
							location.address = result.location // 记录符合打卡规则的地址
							location.ruleId = result.ruleId // 记录符合打卡规则
							this.location = result // 设置地图位置
							this.setLocation(location)
						}
						
						// 打卡上报
						if (this.isReport) {
							this.$emit('change', {
								location: this.prevLocation,
								areaLocation: this.location,
								distance: this.distance,
							})
						}
					}
				}, this.refreshTimeout)
			},
			// 获取当前地理位置
			getLocation() {
				return uni.getLocation({
					type: 'gcj02'
				}).then(res => {
					return res
				}, (err) => {
					uni.showToast({
						icon: 'none',
						title: '请打开手机GPS定位'
					})
				})
			},
			// 设置打卡区域
			setPunchzone(areaLists) {
				const circles = []

				areaLists.map(item => {
					circles.push({
						latitude: item.latitude,
						longitude: item.longitude,
						color: '#69BFBE6A',
						fillColor: '#69BFBE6A',
						radius: item.distance,
						strokeWidth: 2
					})
				})

				this.circles = circles
			},
			// 设置
			setLocation(location) {
				const { latitude, longitude } = location
				// 位置没有变化
				if (this.prevLocation && this.prevLocation.latitude === latitude && this.prevLocation.longitude === longitude) {
					return false
				}

				// 设置地图设置图标
				this.covers = [
					{
						latitude,
						longitude,
						iconPath: './weizhi-red.png'
					}
				]

				// 记录上次的位置信息
				this.prevLocation = location
			},
			// 计算距离
			distanceOfTwoPoint(lat1, lng1, lat2, lng2) {
			  const radLat1 = lat1 * Math.PI / 180.0
			  const radLat2 = lat2 * Math.PI / 180.0
			  const a = radLat1 - radLat2
			  const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0
			  let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)))
			  s = s * 6378.137
			  s = Math.round(s * 1000)

			  return s
			},
			clockIn() {
				if (!this.isInArea) return
				this.$emit('clockInClick', {
					location: this.prevLocation,
					areaLocation: this.location,
					distance: this.distance,
				})
			},
			setTime() {
				this.timer2 = setInterval(() => {
					const { hours, minutes, seconds } = this.getTime()
					const time = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
					this.curTime = time
				}, 1000)
			},
			getTime() {
			  const now = new Date()
			  const hours = now.getHours()
			  const minutes = now.getMinutes()
			  const seconds = now.getSeconds()
			  return { hours, minutes, seconds }
			}
		}
	}
</script>

<style lang="less">
	.map-container {
		.map {
			width: 750rpx;
			/* #ifdef H5 */
			width: 100%;
			/* #endif */
			height: 600rpx;
			background-color: #f0f0f0;
		}
		.in-area {
			.inline {
				color: #17DF63;
				display: inline-flex;
				.icon {
					background: url(./weizhi-green.png) no-repeat;
					background-size: contain;
				}
			}
			.click-in-btn {
				background-color: #6981EE;
			}
		}
		.not-in-area {
			.inline {
				color: #F14948;
				display: inline-flex;
				.icon {
					background: url(./weizhi-red.png) no-repeat;
					background-size: contain;
				}
			}
			.click-in-btn {
				background-color: #FDDDAA;
			}
		}
		.tip {
			font-size: 32rpx;
			font-weight: bold;
			padding: 60rpx 0;
			line-height: 48rpx;
			width: 100%;
			text-align: center;
			.icon {
				width: 48rpx;
				height: 48rpx;
				display: inline-block;
			}
			.des {
				display: inline-block;
				padding-left: 8rpx;
			}
		}
		.click-in-btn {
			width: 280rpx;
			height: 280rpx;
			border-radius: 50%;
			margin: 0 auto;
			color: #fff;
			font-size: 48rpx;
			text-align: center;
			.txt {
				padding: 64rpx 0 0 0;
			}
		}
	}
</style>
